/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.cmp.player.controls;

import static com.cmp.core.constants.InputUIDConstants.*;
import com.cmp.player.abilities.ThrowControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;

/**
 *
 * @author krummer
 */
public class AIControl extends AbstractControl {
    
    private Node lookAt;
    
    @Override
    public void setSpatial(Spatial spatial) {
        super.setSpatial(spatial);

        //make him aim at origin.
        this.getSpatial().setUserData(CURSOR_POS_UID, Vector3f.ZERO);
        
        //look for player.
        if(spatial.getParent() != null) {
            updateLookAt();
        }
        
    }
    
    public void updateLookAt() {

        //look at controlled player (if he can find one.)
        for(Spatial player:spatial.getParent().getChildren()) {
            boolean isPlayer = player.getControl(InputControl.class) != null;
            if(isPlayer) {
                if(this.lookAt == null) {
                    this.lookAt = (Node) player;
                } else {
                    
                    //look at player that is closer.
                    /*float distPlayer = getSpatial().getWorldTranslation()
                            .distance(player.getWorldTranslation());
                    float distNearest = getSpatial().getWorldTranslation().
                            distance(this.lookAt.getWorldTranslation());
                    if(distPlayer < distNearest) {
                        this.lookAt = (Node) player;
                    }*/
                }
            }
        }  
    }
    
    public void setLookAt(Node lookAt) {
        this.lookAt = lookAt;
    }

    @Override
    protected void controlUpdate(float tpf) {
        //refresh lookat.
        if((this.lookAt == null) && (this.getSpatial().getParent() != null)) {
            this.updateLookAt();
        }
        
        //look at other player
        if(this.lookAt != null) {
            Vector3f pos = this.lookAt.getControl(RigidBodyControl.class).getPhysicsLocation().clone();
            Vector3f speed = this.lookAt.getControl(RigidBodyControl.class).getLinearVelocity().clone();
            Vector3f cursor = throwAheadPosition(15.f, 
                    getSpatial().getWorldTranslation(), 
                    pos, 
                    speed);
            this.getSpatial().setUserData(CURSOR_POS_UID, cursor);
        }
        
        //throw ball once you get it.
        this.getSpatial().getControl(ThrowControl.class).execute();
    }
    
    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) {
    }
    
    private Vector3f throwAheadPosition(float throwSpeed, Vector3f sPos, Vector3f tPos, Vector3f tSpeed) {
        float runTime = 0.f;
        Vector3f pos = tPos.clone();
        for(int i = 0; i < 20; i++) {
            pos = tPos.add(tSpeed.mult(runTime));
            float flightTime = pos.subtract(sPos).length() / throwSpeed;
            float error = flightTime - runTime;
            runTime += error;
            if(FastMath.abs(error) < 0.01f) {
                break;
            }
        }
        return pos;
    }

    public Control cloneForSpatial(Spatial spatial) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
}
